#include<stdio.h>
#include<malloc.h>

typedef struct V adj_tb;
typedef struct L link;
struct V{ int count; link* link; };
struct L{ int number;link* next; };

link* new_link(int number){
    link* l = malloc(sizeof(link));
    l->number = number;
    l->next = NULL;
    return l;
}

void adj_tb_add_link(adj_tb* tb,link* l){
    int i; link* cur = tb->link;
    if(cur==NULL){tb->link = l;tb->count=1;return; }
    for(i=1;i<tb->count;i++)cur = cur->next;
    cur->next = l; tb->count++;
}

void adj_tb_del(adj_tb* tb,int n){
    int i,j; link* cur,*tmp;
    for(i=0;i<n;i++){
        cur = tb[i].link;
        for(j=0;j<tb[j].count;j++){
            tmp = cur->next;free(cur);cur=tmp;
        }
    }
    free(tb);
}

void print_adj_tb(const adj_tb* tb,int n){
    int i,j; link* cur;
    printf("<Adjacency Table with %d vert%s>\n",n,n>1?"ices":"ex");
    for(i=0;i<n;i++){
        printf("%4d|",i+1); cur = tb[i].link;
        for(j=0;j<tb[i].count;j++){printf("%d ",cur->number);cur = cur->next;}
        putchar('\n');
    }
}

void cal_in_out_degree(const adj_tb* tb,int n){
    int i,j; link* cur;
    int* out = malloc(sizeof(int)*n);
    for(i=0;i<n;i++)out[i]=0;
    for(i=0;i<n;i++){
        cur = tb[i].link;
        for(j=0;j<tb[i].count;j++){out[cur->number-1]++;cur=cur->next;}
    }
    printf("Index|");for(i=0;i<n;i++)printf("%2d|",i+1);putchar('\n');
    printf("Out-d|");for(i=0;i<n;i++)printf("%2d|",tb[i].count);putchar('\n');
    printf("In-d |");for(i=0;i<n;i++)printf("%2d|",out[i]);putchar('\n');
    free(out);
}


int main(){
    int n,i,j,buf;
    printf("Enter verteice count: ");
    scanf("%d",&n);
    printf("Enter adjacent vertices for each vertex, end with -1:\n");
    adj_tb* tb = malloc(sizeof(adj_tb)*n);
    for(i =0;i<n;i++){
        tb[i].count = 0; tb[i].link = NULL;
        printf("v[%d]> ",i+1);
        for(j=0;j<n;j++){
            scanf("%d",&buf);
            if(buf==-1)break;
            adj_tb_add_link(tb+i,new_link(buf));
        }
    }
    printf("Get Adjacency Table:\n");print_adj_tb(tb,n);
    cal_in_out_degree(tb,n);
    adj_tb_del(tb,n);
    return 0;
}